import React, { useRef, useEffect, useImperativeHandle, forwardRef, useMemo, useState } from 'react';
import { useGLTF, Text } from '@react-three/drei';
import { useSpring, animated } from '@react-spring/three';
// @ts-ignore
import { useDrag } from '@use-gesture/react';
import { useThree } from '@react-three/fiber';
import * as THREE from 'three';

interface TRNAModelProps {
  modelPath: string;
  // 将 position 改为 initialPosition 以明确它是初始位置
  initialPosition?: [number, number, number];
  anticodon: string; // 添加反密码子 prop
  // 修改 onDrop 回调，传递 tRNA 的当前位置和反密码子，并接收一个回调函数来触发返回动画
  onDrop: (currentPosition: [number, number, number], anticodon: string) => void; // 添加拖拽结束回调 prop
  // 添加拖拽开始回调
  onDragStart?: () => void;
  // 控制是否允许拖拽
  canDrag?: boolean;
  // TODO: 添加其他 tRNA 相关的 props，如对应的氨基酸等
}

// 定义暴露给父组件的方法接口
export interface TRNAModelRef {
  returnToInitialPosition: () => void;
  // TODO: 添加其他需要暴露的方法
}

// 创建一个简单的 tRNA 几何体作为后备
const createFallbackTRNA = () => {
  const group = new THREE.Group();
  
  // 创建一个简单的 L 形状代表 tRNA
  const geometry = new THREE.BoxGeometry(1, 0.2, 0.2);
  const material = new THREE.MeshStandardMaterial({ color: '#4CAF50', transparent: true, opacity: 0.8 });
  
  // 垂直部分
  const vertical = new THREE.Mesh(geometry, material);
  vertical.position.set(0, 0.4, 0);
  vertical.scale.set(0.2, 1, 1);
  group.add(vertical);
  
  // 水平部分
  const horizontal = new THREE.Mesh(geometry, material);
  horizontal.position.set(0.4, 0.8, 0);
  group.add(horizontal);
  
  return group;
};

// 使用 forwardRef 允许父组件获取组件内部的引用 (这里用于调用动画)
export const TRNAModel = forwardRef<TRNAModelRef, TRNAModelProps>(
  ({ modelPath, initialPosition = [0, 0, 0], anticodon, onDrop, onDragStart, canDrag }, ref) => {
    const { scene } = useGLTF(modelPath, true);
    const { viewport, camera } = useThree();
    const modelRef = useRef<THREE.Group>(null);
    const isDragging = useRef(false);
    
    // 创建后备模型
    const fallbackModel = useMemo(() => createFallbackTRNA(), []);

    // 判断模型是否加载失败
    const [modelLoadFailed, setModelLoadFailed] = useState(false);
    useEffect(() => {
      // 检查模型是否为空或无效
      if (!scene || !scene.children || scene.children.length === 0) {
        console.warn('tRNA 模型加载失败，使用后备模型');
        setModelLoadFailed(true);
      }
    }, [scene]);

    // 使用 react-spring 管理位置动画
    const [springProps, api] = useSpring(() => ({
      position: initialPosition,
      scale: [1, 1, 1],
      rotation: [0, 0, 0],
      config: { mass: 1, tension: 200, friction: 20 },
    }));

    // 暴露方法给父组件
    useImperativeHandle(ref, () => ({
      returnToInitialPosition: () => {
        api.start({
          position: initialPosition,
          scale: [1, 1, 1],
          rotation: [0, 0, 0],
        });
      },
    }));

    // 处理模型加载
    useEffect(() => {
      if (scene && !modelLoadFailed) {
        scene.traverse((child) => {
          if (child instanceof THREE.Mesh) {
            child.castShadow = true;
            child.receiveShadow = true;
            if (child.material instanceof THREE.Material) {
              child.material = new THREE.MeshStandardMaterial({
                color: '#4CAF50',
                transparent: true,
                opacity: 0.8,
                metalness: 0.5,
                roughness: 0.5,
              });
            }
          }
        });
      }
      
      // 清理函数
      return () => {
        // 确保在组件卸载时释放资源
        if (scene) {
          scene.traverse((child) => {
            if (child instanceof THREE.Mesh) {
              if (child.geometry) {
                child.geometry.dispose();
              }
              if (child.material) {
                if (Array.isArray(child.material)) {
                  child.material.forEach(material => material.dispose());
                } else {
                  child.material.dispose();
                }
              }
            }
          });
        }
      };
    }, [scene, modelLoadFailed]);

    // 使用 useDrag 处理拖拽
    const bind = useDrag(
      ({ active, movement: [mx, my], event, first, last, xy }) => {
        if (event && event.stopPropagation) {
          event.stopPropagation();
        }
        
        // 如果不允许拖拽，则直接返回
        if (canDrag === false) {
          return;
        }
        
        // 如果是拖拽开始且有onDragStart回调，则调用
        if (first && active && onDragStart) {
          onDragStart();
        }
        
        // 更新拖拽状态
        isDragging.current = active;

        // 将屏幕像素移动转换为Three.js世界坐标
        // 为X轴和Y轴使用不同的灵敏度，使左右移动更加灵敏
        const xSensitivity = 0.5; // 增加水平灵敏度
        const ySensitivity = 0.1; // 保持垂直灵敏度适中
        
        const xMove = (mx / viewport.width) * viewport.factor * xSensitivity;
        const yMove = (my / viewport.height) * viewport.factor * ySensitivity;
        
        // 注意：在Three.js中，Y轴向上为正方向，所以需要取反
        const y = -yMove; // 修正：取反使上下移动正确
        const x = xMove;

        // 限制拖拽距离
        const maxDistance = 100; // 合理的拖拽半径
        const distance = Math.sqrt(x * x + y * y);
        
        let adjustedX = x;
        let adjustedY = y;
        
        if (distance > maxDistance) {
          const scale = maxDistance / distance;
          adjustedX *= scale;
          adjustedY *= scale;
        }

        // 计算新位置
        const newPosition = active
          ? [
              initialPosition[0] + adjustedX,
              initialPosition[1] + adjustedY,
              initialPosition[2] + (active ? 0.5 : 0) // 轻微提升，更易于看到
            ]
          : initialPosition;

        // 使用spring动画更新位置，减少抖动
        api.start({
          position: newPosition as [number, number, number],
          scale: active ? [1.2, 1.2, 1.2] : [1, 1, 1],
          // 完全移除旋转效果
          rotation: [0, 0, 0],
          // 当拖拽时，immediate设为true可以减少延迟感
          immediate: active,
          config: active 
            ? { tension: 300, friction: 20 } // 拖拽时更快的响应
            : { mass: 1, tension: 170, friction: 26 } // 释放时平滑返回
        });

        // 拖拽结束时触发onDrop回调
        if (last && !active && onDrop) {
          const currentPosition = [
            initialPosition[0] + adjustedX,
            initialPosition[1] + adjustedY,
            initialPosition[2] + 0.5
          ] as [number, number, number];
          onDrop(currentPosition, anticodon);
        }
      },
      {
        bounds: {
          left: -viewport.width / 2,
          right: viewport.width / 2,
          top: viewport.height / 2,
          bottom: -viewport.height / 2,
        },
        // 增加阻尼，减少抖动
        filterTaps: true,
        rubberband: true,
        // 添加事件选项，使用passive模式提高性能
        eventOptions: { passive: true }
      }
    );

    return (
      <animated.group
        ref={modelRef}
        {...(bind() as any)}
        position={springProps.position}
        scale={springProps.scale}
        rotation={springProps.rotation}
      >
        {/* 根据模型加载状态显示实际模型或后备模型，避免每次渲染都克隆 */}
        {!modelLoadFailed ? (
          <primitive object={scene} dispose={null} />
        ) : (
          <primitive object={fallbackModel} dispose={null} />
        )}
        
        {/* 显示反密码子文本 */}
        <Text
          position={[0, 1.2, 0]}
          fontSize={0.4}
          color="#ffffff"
          anchorX="center"
          anchorY="middle"
        >
          {anticodon}
        </Text>
      </animated.group>
    );
  }
);

// TODO: 创建 CodonTarget 组件
// TODO: 创建 ProteinChain 组件
// TODO: 创建 matching.ts 工具文件
// TODO: 在 DNA.tsx 中集成这些组件和逻辑 